import Utils (tok, at, readInt)
import Data.List (group, sort, sortBy)

data Card = 
    N2 | N3 | N4 | N5 | N6 | N7 | N8 | N9 | N10 | 
    J  | Q  | K  | A
    deriving (Show, Enum, Eq, Ord)

data Type = HC | P | PP | SAME3 | FH | SAME4 | SAME5
    deriving (Show, Enum, Eq, Ord)

type Hand = [Card]
type Bid  = Int

-- 32T3K 765
parseLine :: String -> (Hand, Bid)
parseLine s = 
    (h, b)
    where
        h = map char2Card . at 0 $ tokens
        b = readInt . at 1 $ tokens
        tokens = tok " " s
        char2Card c = 
            case c of 
                '2' -> N2
                '3' -> N3
                '4' -> N4
                '5' -> N5
                '6' -> N6
                '7' -> N7
                '8' -> N8
                '9' -> N9
                'J' -> J
                'Q' -> Q
                'K' -> K
                'A' -> A

handType :: Hand -> Type
handType h =
    case freqs of
        [5]       -> SAME5
        [4, 1]    -> SAME4
        [3, 2]    -> FH
        [3, 1, 1] -> SAME3
        [2, 2, 1] -> PP
        [2, 1, 1, 1] -> P
        (1:_)     -> HC
        _         -> error "handType error"
    where
        freqs = reverse . sort . map length . group . sort $ h

compHands :: Hand -> Hand -> Ordering
compHands h1 h2
    | compHandType h1 h2 /= Eq = compHandType h1 h2
    | otherwise                = compLTR h1 h2
    where
        compHandType x y = compare (handType x) (handType y)

        compLTR [] [] = EQ
        compLTR (c:cs) (d:ds) 
            | c /= d    = compare c d 
            | otherwise = compLTR cs ds

main = do
    contents <- readFile "input.txt"

    let input = map parseLine . lines $ contents

    print $ sum
          . zipWith (*) [1..]
          . map snd
          . sortBy (\x y -> compHands (fst x) (fst y))
          $ input